package com.example.oauth.utils;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.google.common.collect.Queues;
import org.apache.http.util.Asserts;
import org.springframework.util.Assert;

import javax.annotation.Nonnull;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Queue;

public final class JavaTypeFactory {

    private JavaTypeFactory() {

    }

    /**
     * 获取缓存的JavaType，如果不存在，则调用TypeFactory创建
     *
     * @param
     * @return
     */

    @Nonnull
    public static JavaType constructType(@Nonnull Type clazz) {
        return TypeFactory.defaultInstance().constructType(clazz);
    }


    @Nonnull
    public static JavaType constructType(@Nonnull List<Class<?>> clazzList) {
        Assert.notEmpty(clazzList, "clazzList is null");
        Queue<Class<?>> queue = Queues.newArrayDeque(clazzList);
        return constructType(queue);
    }


    @Nonnull
    private static JavaType constructType(@Nonnull Queue<Class<?>> classQueue) {
        Class clazz = classQueue.poll();
        Assert.notNull(clazz, "clazz");

        if (clazz.getTypeParameters().length == 0
                || classQueue.size() == 0) {
            return TypeFactory.defaultInstance().constructType(clazz);
        }
        JavaType[] typeParameters = new JavaType[clazz.getTypeParameters().length];
        for (int index = 0; index < typeParameters.length; index++) {
            typeParameters[index] = constructType(classQueue);
        }
        return TypeFactory.defaultInstance().constructParametricType(clazz, typeParameters);
    }


    @Nonnull
    public static JavaType construtGenericcParameter(@Nonnull Class<?> subClazz, Class<?> genericClazz) {
        return construtGenericcParameter(subClazz, genericClazz, 0);
    }

    @Nonnull
    public static JavaType construtGenericcParameter(@Nonnull Class<?> instanceClazz, Class<?> genericClazz, int parameterIndex) {
        JavaType javaType = JavaTypeFactory.constructType(instanceClazz);
        return javaType.findTypeParameters(genericClazz)[parameterIndex];
    }



}
